/*
 * @Author: your name
 * @Date: 2022-05-01 06:35:50
 * @LastEditTime: 2022-05-08 11:47:42
 * @LastEditors: daniel_du dll_2018@126.com
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: /safe_transmission_platform/tests/test_rsa.cc
 */

#include <openssl/rsa.h>
#include <iostream>
#include <string>
#include <fstream>
#include <cstdio>
#include <openssl/pem.h>
#include "myrsa.h"
#include "log.h"
#include <cstring>

#ifdef WIN_32
extern "C"
{
#include <openssl/applink.c>
}
#endif
static sylar::Logger::ptr g_logger=DANIEL_LOG_NAME("system");

void generateRsaKey()
{
    RSA *rsa = RSA_new();
    BIGNUM *e = BN_new();
    BN_set_word(e, 12345);
    RSA_generate_key_ex(rsa, 1024, e, nullptr);
    //将密钥写入内存的两种方式
    // RSA* publicRsa=RSAPublicKey_dup(rsa);
    // RSA* privateRsa=RSAPrivateKey_dup(rsa);
#if 0
    FILE* fp=fopen("public.pem","w");
    PEM_write_RSA_PUBKEY(fp,rsa);
    fclose(fp);
    fp=fopen("private.pem","w");
    PEM_write_RSAPrivateKey(fp,rsa,nullptr,nullptr,0,nullptr,nullptr);
    fclose(fp);
#else
    BIO *bio = BIO_new_file("public.pem", "w");
    PEM_write_bio_RSAPublicKey(bio, rsa);
    BIO_free(bio);
    bio = BIO_new_file("private.pem", "w");
    PEM_write_bio_RSAPrivateKey(bio, rsa, nullptr, nullptr, 0, nullptr, nullptr);
    BIO_free(bio);
#endif
}
void printUint8(uint8_t *start, int length)
{
    for (int i = 0; i < length; i++)
    {
        printf("%d\t", *(start + i));
    }
    printf("\n");
}

void encrypoAndDecrypo(const std::string& str)
{
    daniel::MyRsa::ptr myRsa(new daniel::MyRsa(daniel::MyRsa::GenerateKeys));
    myRsa->generateKeys(1024);

    //测试使用string封装的API
    std::string to;
    myRsa->publicEncrypt(str, to);
    DANIEL_LOG_DEBUG(g_logger)<< "after publicEncrypt:" << to << std::endl;
    std::string to2;
    myRsa->privateDecrypt(to, to2);
    DANIEL_LOG_DEBUG(g_logger) << "after privateDecrypt:" << to2 << std::endl;
    //测试 私钥加密，公钥解密
    myRsa->privateEncrypt(str,to);
    myRsa->publicDecrypt(to,to2);
    DANIEL_LOG_DEBUG(g_logger)<<"after publicDecrypt:"<<to2<<std::endl;
}

void signAndVerify()
{
    daniel::MyRsa::ptr rsaPublic(new daniel::MyRsa(daniel::MyRsa::LoadPublicKey, "./public.pem"));
    daniel::MyRsa::ptr rsaPrivate(new daniel::MyRsa(daniel::MyRsa::LoadPrivateKey, "./private.pem"));
    //使用私钥签名，使用公钥验证
    std::string words("publicKey:-----BEGIN RSA PUBLIC KEY-----MIGIAoGBAJuy7d0GOXwBJi1Uk4B2TmZ111111111111111111111");
    std::string retData;
    rsaPrivate->RSA_hashsign(daniel::MyRsa::SignSHA256, words, retData);
    retData[1] += 1;
    bool ret = rsaPublic->RSA_hashverify(daniel::MyRsa::SignSHA256, words, retData);
    std::cout << "ret=" << ret << std::endl;
}

void encodeAndDecode(const std::string& str)
{
    std::string encodeWords=daniel::MyRsa::base64Encode(str);
    DANIEL_LOG_DEBUG(g_logger)<<"base64 encode msg:"<<encodeWords<<std::endl;
    std::string decodeWords=daniel::MyRsa::base64Decode(encodeWords);
    DANIEL_LOG_DEBUG(g_logger)<<"base64 decode msg:"<<decodeWords<<std::endl;
}
void testCopyBuf()
{
    char buf[53];
    memset(buf,0,32);
    for (int i=0;i<26;i++){
        buf[i]='a'+i;
    }
    buf[26]='\0';
    for(int i=0;i<26;i++){
        buf[i+27]='A'+i;
    }
    std::string str;
    for(int i=0;i<53;i++){
        str.append(1,buf[i]);
    }
    std::cout<<"testCopyBuf:"<<str<<"\ttest_copytBuf size:"<<std::endl;
}

int main()
{
    // generateRsaKey();
    // signAndVerify();
    // encrypoAndDecrypo();
    encodeAndDecode("PCAzEnWqrL*I8U4g");
    encodeAndDecode("G%iE$MUqabQ&WZRC");
    encodeAndDecode("6X(KsM#E)g1oaTL8");
    encodeAndDecode("Gi4C0wnXr^Tlbop(");

    encrypoAndDecrypo("PCAzEnWqrL*I8U4g");
    encrypoAndDecrypo("G%iE$MUqabQ&WZRC");
    encrypoAndDecrypo("6X(KsM#E)g1oaTL8");
    encrypoAndDecrypo("Gi4C0wnXr^Tlbop(");
    // std::string testStr;
    // const char* buf="293023jifladlfja\0jweiwojeifjwef";
    // for(size_t i=0;i<strlen(buf);i++){
    //     testStr.push_back(buf[i]);
    //     std::cout<<"i="<<i;
    // }
    // std::cout<<std::endl;
    // std::cout<<"testStr:"<<testStr<<std::endl;
    testCopyBuf();
}